freeslot(
	"MT_CHARCHAN_SONIC",
	"MT_CHARCHAN_TAILS",
	"MT_CHARCHAN_KNUX",
	"MT_CHARCHAN_AMY",
	"MT_CHARCHAN_FANG",
	"MT_CHARCHAN_METAL",
	"S_CHARCHAN_SONIC",
	"S_CHARCHAN_TAILS",
	"S_CHARCHAN_KNUX",
	"S_CHARCHAN_AMY",
	"S_CHARCHAN_FANG",
	"S_CHARCHAN_METAL",
	"SPR_CRCN"
)
addHook("MobjDamage", function(mobj)
	if mapheaderinfo[gamemap].lvlttl ~= "Desolate Dune" then return end
	return true
end, MT_BLUECRAWLA)

addHook("TouchSpecial", function(mobj, player)
	if mapheaderinfo[gamemap].lvlttl ~= "Desolate Dune" then return end
	P_DamageMobj(player)
	P_KillMobj(mobj)
	S_StartSound(mobj, sfx_itemup)
	print("Get Ringed!")
	return true
end, MT_RING)

local minspeed = (ANG1 * 3) / 2
local defaultskin
local postskin
local lastpost

-- this hook returns the player to the skin they were at when starting the level.
addHook("PlayerSpawn", function(player)
	if mapheaderinfo[gamemap].lvlttl == "Desolate Dune" then return end
	if defaultskin == nil then return end
	R_SetPlayerSkin(player, defaultskin)
	defaultskin = nil
end)

addHook("PlayerSpawn", function(player)
	if mapheaderinfo[gamemap].lvlttl ~= "Desolate Dune" then return end
	if defaultskin == nil then defaultskin = skins[player.skin].name end
	if postskin == nil then postskin = defaultskin end
	R_SetPlayerSkin(player, postskin)
end)

addHook("PlayerThink", function(player)
	if mapheaderinfo[gamemap].lvlttl ~= "Desolate Dune" then return end
	if lastpost ~= player.starpostnum
		lastpost = player.starpostnum
		postskin = skins[player.skin].name
	end
end)

local function iconSpeen(mobj)
	mobj.angle = $ + mobj.rhspinspd
	if mobj.rhspinspd > minspeed
		mobj.rhspinspd = $ - FRACUNIT*16
	end
	if mobj.rhspinspd < minspeed
		mobj.rhspinspd = minspeed
	end
end

local function changeCharacter(mobj, player, skin)
	mobj.rhspinspd = min(max(minspeed * (player.speed / (FRACUNIT * 4 )), mobj.rhspinspd), INT32_MAX) -- speen
	if skins[player.skin].name == skin then return end -- skip change if the player already has the skin
	R_SetPlayerSkin(player, skin) -- change
end

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_BLUE
end, MT_CHARCHAN_SONIC)

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_ORANGE
end, MT_CHARCHAN_TAILS)

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_RED
end, MT_CHARCHAN_KNUX)

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_ROSY
end, MT_CHARCHAN_AMY)

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_LAVENDER
end, MT_CHARCHAN_FANG)

addHook("MobjSpawn", function(mobj)
	mobj.rhspinspd = minspeed
	mobj.color = SKINCOLOR_COBALT
end, MT_CHARCHAN_METAL)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_SONIC)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_TAILS)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_KNUX)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_AMY)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_FANG)

addHook("MobjThinker", function(mobj)
	iconSpeen(mobj)
end, MT_CHARCHAN_METAL)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "sonic")
	return true
end, MT_CHARCHAN_SONIC)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "tails")
	return true
end, MT_CHARCHAN_TAILS)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "knuckles")
	return true
end, MT_CHARCHAN_KNUX)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "amy")
	return true
end, MT_CHARCHAN_AMY)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "fang")
	return true
end, MT_CHARCHAN_FANG)

addHook("TouchSpecial", function(mobj, player)
	if player.player == nil then return end
	changeCharacter(mobj, player.player, "metalsonic")
	return true
end, MT_CHARCHAN_METAL)

mobjinfo[MT_CHARCHAN_SONIC]={
//$Category Character Change
//$Name Change (Sonic)
//$Sprite CRCNA0
	doomednum = 3331,
	spawnstate = S_CHARCHAN_SONIC,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

mobjinfo[MT_CHARCHAN_TAILS]={
//$Category Character Change
//$Name Change (Tails)
//$Sprite CRCNB0
	doomednum = 3332,
	spawnstate = S_CHARCHAN_TAILS,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

mobjinfo[MT_CHARCHAN_KNUX]={
//$Category Character Change
//$Name Change (Knuckles)
//$Sprite CRCNC0
	doomednum = 3333,
	spawnstate = S_CHARCHAN_KNUX,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

mobjinfo[MT_CHARCHAN_AMY]={
//$Category Character Change
//$Name Change (Amy)
//$Sprite CRCND0
	doomednum = 3334,
	spawnstate = S_CHARCHAN_AMY,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

mobjinfo[MT_CHARCHAN_FANG]={
//$Category Character Change
//$Name Change (Fang)
//$Sprite CRCNE0
	doomednum = 3335,
	spawnstate = S_CHARCHAN_FANG,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

mobjinfo[MT_CHARCHAN_METAL]={
//$Category Character Change
//$Name Change (Metal Sonic)
//$Sprite CRCNF0
	doomednum = 3336,
	spawnstate = S_CHARCHAN_METAL,
	spawnhealth = 1,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,	
	flags = MF_NOGRAVITY|MF_NOCLIP|MF_SPECIAL
}

states[S_CHARCHAN_SONIC] = {
        sprite = SPR_CRCN,
        frame = A|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}

states[S_CHARCHAN_TAILS] = {
        sprite = SPR_CRCN,
        frame = B|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}

states[S_CHARCHAN_KNUX] = {
        sprite = SPR_CRCN,
        frame = C|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}

states[S_CHARCHAN_AMY] = {
        sprite = SPR_CRCN,
        frame = D|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}

states[S_CHARCHAN_FANG] = {
        sprite = SPR_CRCN,
        frame = E|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}

states[S_CHARCHAN_METAL] = {
        sprite = SPR_CRCN,
        frame = F|FF_FULLBRIGHT|FF_PAPERSPRITE,
        tics = -1
}